"""
百度OCR工具模块

该模块提供身份证识别功能，通过百度AI平台的OCR服务实现身份证信息的自动提取。
支持识别身份证正面（人像面）和背面（国徽面）的关键信息。
"""

import base64
import requests
from config.settings import settings

# 从配置文件读取百度AI平台的认证密钥
# 这些密钥需要在百度AI开放平台申请获取
ACCESS_KEY_ID = settings.ACCESS_KEY_ID
ACCESS_KEY_SECRET = settings.ACCESS_KEY_SECRET

# 百度AI平台的认证和OCR服务URL
TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token"  # 获取访问令牌的接口
OCR_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard"  # 身份证OCR识别接口


def get_access_token() -> str | None:
    """
    获取百度AI平台的访问令牌
    
    通过API Key和Secret Key获取访问令牌，用于后续的OCR识别请求。
    访问令牌有一定有效期，过期后需要重新获取。
    
    Returns:
        str | None: 成功时返回访问令牌字符串，失败时返回None
        

    """
    # 检查必要的配置参数是否存在
    if not ACCESS_KEY_ID or not ACCESS_KEY_SECRET:
        return None
    
    try:
        # 向百度AI平台发送请求获取访问令牌
        resp = requests.post(
            TOKEN_URL,
            params={
                "grant_type": "client_credentials",      # 使用client_credentials方式获取令牌
                "client_id": ACCESS_KEY_ID,              # API Key
                "client_secret": ACCESS_KEY_SECRET,      # Secret Key
            },
            timeout=10,  # 设置10秒超时
        )
        # 检查HTTP响应状态码，如果出错会抛出异常
        resp.raise_for_status()
        # 从JSON响应中提取访问令牌
        return resp.json().get("access_token")
    except Exception:
        # 发生任何异常都返回None
        return None


def ocr_idcard(image_bytes: bytes, side: str = "front") -> dict:
    """
    调用百度 OCR API 识别身份证
    
    对上传的身份证图片进行OCR识别，提取身份证上的关键信息。
    支持识别身份证正面（人像面）和背面（国徽面）的不同信息。
    """
    # 获取访问令牌用于OCR识别
    token = get_access_token()
    # 如果获取令牌失败，返回错误信息
    if not token:
        return {"error": "ACCESS_TOKEN_ERROR", "message": "获取Access Token失败，检查密钥配置"}

    # 将图片字节数据转换为base64编码格式，这是百度OCR接口要求的格式
    image_base64 = base64.b64encode(image_bytes).decode("utf-8")
    
    try:
        # 调用百度OCR身份证识别接口
        resp = requests.post(
            f"{OCR_URL}?access_token={token}",  # 在URL中附带访问令牌
            headers={
                "Content-Type": "application/x-www-form-urlencoded",  # 表单数据格式
                "Accept": "application/json",  # 期望返回JSON格式数据
            },
            data={
                "image": image_base64,           # 图片base64数据
                "id_card_side": side,            # 身份证面（front/back）
                "detect_direction": "true",      # 检测图像方向
                "accuracy": "normal",            # 识别精度（normal/high）
            },
            timeout=20,  # 设置20秒超时
        )
        # 检查HTTP响应状态码
        resp.raise_for_status()
        # 解析JSON格式的响应数据
        result = resp.json()
        
        # 打印原始结果用于调试
        print(f"[DEBUG] Baidu OCR raw result: {result}")
        
        # 从OCR结果中提取关键字段信息
        extracted = {}
        # 检查响应中是否包含识别结果
        if "words_result" in result:
            # 获取识别出的文字结果
            words = result["words_result"]
            
            # 根据身份证面提取不同的信息
            if side == "front":
                # 人像面：姓名、身份证号、性别、民族、出生、住址
                extracted["name"] = words.get("姓名", {}).get("words", "")                    # 姓名
                extracted["id_number"] = words.get("公民身份号码", {}).get("words", "")        # 身份证号
                extracted["gender"] = words.get("性别", {}).get("words", "")                  # 性别
                extracted["nation"] = words.get("民族", {}).get("words", "")                  # 民族
                extracted["birthday"] = words.get("出生", {}).get("words", "")                # 出生日期
                extracted["address"] = words.get("住址", {}).get("words", "")                # 住址
            else:
                # 国徽面：签发机关、有效期限
                extracted["issue_authority"] = words.get("签发机关", {}).get("words", "")     # 签发机关
                extracted["validity_period"] = words.get("签发日期", {}).get("words", "")     # 有效期限
            
            print(f"[DEBUG] Extracted data: {extracted}")
        else:
            # 如果响应中没有识别结果，打印警告信息
            print(f"[WARN] No words_result in OCR response")
        
        # 将提取的信息添加到结果中
        result["extracted"] = extracted
        return result
    except requests.RequestException as e:
        # 捕获网络请求异常，返回错误信息
        return {"error": "REQUEST_ERROR", "message": str(e)}
